import { BrowserInfo } from '@/utils/browser';
import api from '@/api';
import { Message } from 'element-ui';
import { nmCryptokit } from '@/utils/nmCryptoKit';
import { fqlCryptokit } from '@/utils/fqlCryptoKit';
import { cSharpCryptokit } from '@/utils/cSharpCryptoKit';

// 研究模块
const CryptoKit = {
    state: {
        CryptoKit: null,
        userSn: '',
        isSigning: false
    },
    getters: {},
    mutations: {
        SET_CRYPTOKIT_DATA (state, data) {
            state.CryptoKit = data;
        },
        SET_USERSN_DATA (state, data) {
            state.userSn = data;
        },
        SET_ISSIGNING_DATA (state, data) {
            state.isSigning = data;
        }
    },
    actions: {
        initCryptoKit (context) {
            const userClient = context.getters.userClient;

            if (userClient == '1') {
                // 富易客户端初始化流程
                context.dispatch('newFqlInstance');
            } else if (userClient == '2') {
                // 道合PC客户端初始化流程
                context.dispatch('initCSCryptoKit');
            } else {
                // 浏览器初始化流程
                context.dispatch('initBroswerCryptoKit');
            }
        },
        newFqlInstance ({ commit, state }) {
            if (state.CryptoKit == null) {
                console.info('CryptoKit fql Bingo');
                var browser = BrowserInfo().name;

                commit('SET_CRYPTOKIT_DATA', new fqlCryptokit(browser));
            } else {
                console.info('CryptoKit already initialed');
            }
        },
        initCSCryptoKit ({ commit, state }) {
            if (state.CryptoKit == null) {
                console.info('CryptoKit C# Bingo');
                var browser = BrowserInfo().name;

                commit('SET_CRYPTOKIT_DATA', new cSharpCryptokit(browser));
                state.CryptoKit.init();
            } else {
                console.info('CryptoKit already initialed');
            }
        },
        initFqlCryptoKit ({ commit, state }) {
            console.info('qtCreated');
            var hostVer;
            var extensionVer;
            state.CryptoKit.init()
                .then(function (response) {
                    return state.CryptoKit.getExtensionVersion();
                })
                .then(function (response) {
                    extensionVer = response.result;
                    console.info('extensionVer', extensionVer);
                    return state.CryptoKit.getHostVersion();
                })
                .then(function (response) {
                    console.info(response);
                    hostVer = response.result;
                    // TODO 从服务器获取插件版本
                    // if (('Chrome' == browser && that.compareVersion(extensionVer, "3.4.0.4") < 0)) {
                    //     alert('Please install host');
                    // } else {
                    //     console.info('加载成功');
                    // }
                })
                .catch(function (response) {
                    console.info(response);
                    alert('Please install host');
                });
            console.info(state.CryptoKit);
            console.info('=============================');
        },
        initBroswerCryptoKit ({ commit, state }) {
            if (state.CryptoKit == null) {
                var hostVer;
                var extensionVer;
                var browser = BrowserInfo().name;

                console.info('CryptoKit for %s Bingo', browser);

                // that.chromeExtensionVer = undefined;

                commit('SET_CRYPTOKIT_DATA', new nmCryptokit(browser));
                state.CryptoKit.init()
                    .then(function (response) {
                        return state.CryptoKit.getExtensionVersion();
                    })
                    .then(function (response) {
                        extensionVer = response.result;
                        console.info('extensionVer', extensionVer);
                        return state.CryptoKit.getHostVersion();
                    })
                    .then(function (response) {
                        console.info(response);
                        hostVer = response.result;
                        // TODO 从服务器获取插件版本
                        // if (('Chrome' == browser && that.compareVersion(extensionVer, "3.4.0.4") < 0)) {
                        //     alert('Please install host');
                        // } else {
                        //     console.info('加载成功');
                        // }
                    })
                    .catch(function (response) {
                        console.info(response);
                        alert('Please install host');
                    });
                console.info(state.CryptoKit);
                console.info('=============================');
            } else {
                console.info('CryptoKit already initialed');
            }
        },
        loadUkey ({ commit, state, rootGetters }, BUSIN_ACCOUNT) {
            const userClient = rootGetters.userClient;
            console.info('verifyUkey', BUSIN_ACCOUNT);
            return new Promise((resolve, reject) => {
                api.incomeReceipts.getUkeyCerts({
                    BUSIN_ACCOUNT: BUSIN_ACCOUNT
                }, { showErrorNotify: 0 }).then(async ukeyRes => {
                    console.info(ukeyRes);
                    console.info('verifyUkey success');
                    const ukeys = ukeyRes.data;
                    if (ukeys.length > 0) {
                        // 本地Ukey证书校验，2022.12.7 增加多证书校验
                        for (let i = 0; i < ukeys.length; i++) {
                            commit('SET_USERSN_DATA', ukeys[i].cert_sn);
                            const sn = parseInt(ukeys[i].cert_sn).toString(16);

                            try {
                                const selectRes = await state.CryptoKit.selectCertificate('', '', sn, '');
                                if ((userClient === '2' && selectRes == 0) || (userClient !== '2' && selectRes.errorcode == 0)) {
                                    // 选择证书成功
                                    resolve({
                                        retCode: 0,
                                        msg: '用户证书加载成功'
                                    });
                                    return;
                                } else {
                                    if (i == ukeys.length - 1) {
                                        reject(new Error('证书选择失败，请插入UKey重试'));
                                    } else {
                                        continue;
                                    }
                                }
                            } catch (e) {
                                state.CryptoKit.getLastErrorDesc()
                                    .then(errDesc => {
                                        console.error(errDesc);
                                        // reject(errDesc);
                                    });
                                if (i == ukeys.length - 1) {
                                    reject(new Error('未找到用户对应证书信息，请确保插入正确Ukey后重试'));
                                } else {
                                    continue;
                                }
                            }
                        }
                    }
                }).catch(err => {
                    console.error(err);
                    reject(new Error('用户证书信息为空，请先到柜台办理证书业务'));
                });
            });
        },
        sign ({ commit, state, rootGetters }, strSource) {
            const userClient = rootGetters.userClient;
            return new Promise((resolve, reject) => {
                if (state.CryptoKit == null || state.userSn == null) {
                    reject(new Error('请先initCryptoKit实例化控件并使用loadUkey加载控件'));
                }
                if (state.isSigning === true) {
                    resolve({
                        retCode: -1,
                        msg: '控件忙，无法继续'
                    });
                } else {
                    commit('SET_ISSIGNING_DATA', true);
                    state.CryptoKit.signMsgPKCS1(strSource, 'SHA-1').then(signRes => {
                        if (userClient == '2') {
                            resolve({
                                retCode: 0,
                                result: signRes
                            });
                        } else {
                            if (signRes.errorcode == 0) {
                                resolve({
                                    retCode: 0,
                                    result: signRes.result
                                });
                            } else {
                                reject(new Error('Ukey签名失败，请联系管理员'));
                            }
                        }
                        commit('SET_ISSIGNING_DATA', false);
                    }).catch(err => {
                        commit('SET_ISSIGNING_DATA', false);

                        state.CryptoKit.getLastErrorDesc()
                            .then(errDesc => {
                                console.info(errDesc);
                                reject(errDesc);
                            });
                        // reject(new Error('Ukey签名失败，请联系管理员'));
                    });
                }
            });
        },
        /**
         *
         * @param dispatch
         * @param commit
         * @param state
         * @param payload strSource、BUSI_ACCOUNT、agreementId、signType、PROD_CODE、signStatus、step、recordId
         */
        signFlow ({ dispatch, commit, state }, payload) {
            return new Promise((resolve, reject) => {
                dispatch('sign', payload['strSource'])
                    .then(signRes => {
                        const signResult = signRes.result;

                        // 2. 获取流水号
                        api.incomeReceipts.getProtocolSn({
                            BUSIN_ACCOUNT: payload['BUSI_ACCOUNT']
                        }, { showErrorNotify: 0 })
                            .then(protocolRes => {
                                console.info('2. protocolRes', protocolRes);
                                const ukeyFlow = protocolRes.data[0].ukey_serial_no;

                                // 3. 大协议验签
                                api.incomeReceipts.largeProtocolVerifySign({
                                    BUSIN_ACCOUNT: payload['BUSI_ACCOUNT'],
                                    ZS_NO: state.userSn,
                                    EN_PD_AGREEMENT_ID: payload['agreementId'],
                                    SING_DATA: signResult,
                                    SERIAL_NO: ukeyFlow
                                }, { showErrorNotify: 0 })
                                    .then(signVerifyRes => {
                                        // 4. 记录协议流水
                                        api.incomeReceipts.postProtocolSn({
                                            SIGN_TYPE: payload['signType'],
                                            BUSIN_ACCOUNT: payload['BUSI_ACCOUNT'],
                                            PROD_CODE: payload['PROD_CODE'],
                                            CONTRACT_NO: payload['agreementId'],
                                            ZS_NO: state.userSn,
                                            SIGN_STATUS: payload['signStatus'],
                                            STEP_RECORD: payload['step'],
                                            RECORD_ID: payload['recordId']
                                        }, { showErrorNotify: 0 }).then(res => {
                                            resolve(res);
                                        }).catch(err => {
                                            reject(err);
                                        });
                                    }).catch(err => {
                                    reject(err);
                                    Message.warning('验签失败，请联系管理员');
                                });
                            })
                            .catch(err => {
                                reject(err);
                                Message.warning('签名失败[获取签名流水]，请联系管理员');
                            });
                    })
                    .catch(err => {
                        console.info(err);
                        if (err.errorcode == 0) {
                            Message.warning(err.result);
                        }
                        reject(err);
                    });
            });
        }
    }
};

export default CryptoKit;
